/*  -*- mode: c++; coding: utf-8; c-file-style: "stroustrup"; -*-

    Copyright 2008 Asier Aguirre <asier.aguirre@gmail.com>
    This file is part of Intromit.

    Intromit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Intromit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Intromit.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "gendata_common.hh"
#include "util.hh"

const char *gendata_type_strings[]=
{
    "Class",                 // 0
    "Inheritance",
    "Member",
    "Member vector,n,max",
    "Member object",         // 4
    "Method",
    "Parameter",
    "char*",
    "obj*",                  // 8
    "func*",
    "char",
    "<subroutine>",
    "int",                   // 12
    "unsigned int",
    "float",
    "double",
    "long long",             // 16
    "unsigned long long",
    "pointer",
    "reference count",
    "void*",                 // 20
    "Member std_vector_impl",
    "reference",
    "short",
    "unsigned short",        // 24
    "enum",
    "<enum_value>",
    "unsigned char",
    "[]",                    // 28
    "<subrange>",
    "...",
    "Variable",
    "const_char*",           // 32
    "bool",
    NULL
};

// CLASS
int gendata_struct_class[]=
{
    GENDATA_CLASS,           // first parameter is for checking
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_SIZE,
    GENDATA_NAMESPACE,
    GENDATA_ATTR,
    GENDATA_VTABLE_LINKAGE,
    GENDATA_GENDATA_RESERVE, // reserved for run-time extended info
    GENDATA_GENDATA_VAR,
    GENDATA_META_LAST
};

// INHERITANCE
int gendata_struct_inheritance[]=
{
    GENDATA_INHERITANCE,
    GENDATA_GENDATA_TYPE,
    GENDATA_LOCATION,
    GENDATA_TYPE,
    GENDATA_META_LAST
};

// MEMBER
int gendata_struct_member[]=
{
    GENDATA_MEMBER,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_LOCATION,
    GENDATA_TYPE,
    GENDATA_ATTR,
    GENDATA_META_LAST
};

// GENDATA_MEMBER_VECTOR_N_MAX
int gendata_struct_member_vector_n_max[]=
{
    GENDATA_MEMBER_VECTOR_N_MAX,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_TYPE,
    GENDATA_ATTR,
    GENDATA_LOCATION,
    GENDATA_GENDATA_GOTO_NEXT,
    GENDATA_LOCATION,
    GENDATA_GENDATA_GOTO_NEXT,
    GENDATA_LOCATION,
    GENDATA_META_LAST
};

// MEMBER_OBJECT
int gendata_struct_member_object[]=
{
    GENDATA_MEMBER_OBJECT,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_LOCATION,
    GENDATA_TYPE,
    GENDATA_ATTR,
    GENDATA_META_LAST
};

// METHOD
int gendata_struct_method[]=
{
    GENDATA_METHOD,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_TYPE,
    GENDATA_ATTR,
    GENDATA_LINKAGE,
    GENDATA_IS_CTOR,
    GENDATA_VTABLE,
    GENDATA_GENDATA_VAR,
    GENDATA_META_LAST
};

// PARAMETER
int gendata_struct_parameter[]=
{
    GENDATA_PARAMETER,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_TYPE,
    GENDATA_ARTIFICIAL,
    GENDATA_META_LAST
};

// GENDATA_CHARP
int gendata_struct_charp[]=
{
    GENDATA_CHARP,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_OBJECT_POINTER
int gendata_struct_object_pointer[]=
{
    GENDATA_OBJECT_POINTER,
    GENDATA_GENDATA_TYPE,
    GENDATA_TYPE,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_FUNCTION_POINTER
int gendata_struct_function_pointer[]=
{
    GENDATA_FUNCTION_POINTER,
    GENDATA_GENDATA_TYPE,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_CHAR
int gendata_struct_char[]=
{
    GENDATA_CHAR,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_SUBROUTINE
int gendata_struct_subroutine[]=
{
    GENDATA_SUBROUTINE,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_NAMESPACE,
    GENDATA_TYPE,
    GENDATA_LINKAGE,
    GENDATA_GENDATA_VAR,
    GENDATA_META_LAST
};

// GENDATA_INT
int gendata_struct_int[]=
{
    GENDATA_INT,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_UNSIGNED_INT
int gendata_struct_unsigned_int[]=
{
    GENDATA_UNSIGNED_INT,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_FLOAT
int gendata_struct_float[]=
{
    GENDATA_FLOAT,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_DOUBLE
int gendata_struct_double[]=
{
    GENDATA_DOUBLE,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_LONG_LONG
int gendata_struct_long_long[]=
{
    GENDATA_LONG_LONG,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_UNSIGNED_LONG_LONG
int gendata_struct_unsigned_long_long[]=
{
    GENDATA_UNSIGNED_LONG_LONG,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_POINTER
int gendata_struct_pointer[]=
{
    GENDATA_POINTER,
    GENDATA_GENDATA_TYPE,
    GENDATA_TYPE,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_REFERENCE_COUNT
int gendata_struct_reference_count[]=
{
    GENDATA_REFERENCE_COUNT,
    GENDATA_GENDATA_TYPE,
    GENDATA_LOCATION,
    GENDATA_META_LAST
};

// GENDATA_VOID_POINTER
int gendata_struct_void_pointer[]=
{
    GENDATA_VOID_POINTER,
    GENDATA_GENDATA_TYPE,
    GENDATA_META_LAST
};

// GENDATA_MEMBER_STD_VECTOR_IMPL
int gendata_struct_member_std_vector_impl[]=
{
    GENDATA_MEMBER_STD_VECTOR_IMPL,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_TYPE,
    GENDATA_LOCATION,
    GENDATA_GENDATA_GOTO_NEXT,
    GENDATA_LOCATION,
    GENDATA_GENDATA_GOTO_NEXT,
    GENDATA_LOCATION,
    GENDATA_META_LAST
};

// GENDATA_REFERENCE
int gendata_struct_reference[]=
{
    GENDATA_REFERENCE,
    GENDATA_GENDATA_TYPE,
    GENDATA_TYPE,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_SHORT
int gendata_struct_short[]=
{
    GENDATA_SHORT,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_UNSIGNED_SHORT
int gendata_struct_unsigned_short[]=
{
    GENDATA_UNSIGNED_SHORT,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_ENUM
int gendata_struct_enum[]=
{
    GENDATA_ENUM,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_DOC,
    GENDATA_NAMESPACE,
    GENDATA_ATTR,
    GENDATA_GENDATA_VAR,
    GENDATA_META_LAST
};

// GENDATA_ENUM_VALUE
int gendata_struct_enum_value[]=
{
    GENDATA_ENUM_VALUE,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_CONST_VALUE,
    GENDATA_META_LAST
};

// GENDATA_UNSIGNED_CHAR
int gendata_struct_unsigned_char[]=
{
    GENDATA_UNSIGNED_CHAR,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_ARRAY_TYPE
int gendata_struct_array_type[]=
{
    GENDATA_ARRAY_TYPE,
    GENDATA_GENDATA_TYPE,
    GENDATA_TYPE,
    GENDATA_GENDATA_VAR,
    GENDATA_META_LAST
};

// GENDATA_SUBRANGE
int gendata_struct_subrange[]=
{
    GENDATA_SUBRANGE,
    GENDATA_GENDATA_TYPE,
    GENDATA_UPPER_BOUND,
    GENDATA_META_LAST
};

// GENDATA_UNSPEC_PARAM
int gendata_struct_unspec_param[]=
{
    GENDATA_UNSPEC_PARAM,
    GENDATA_GENDATA_TYPE,
    GENDATA_META_LAST
};

// GENDATA_VARIABLE
int gendata_struct_variable[]=
{
    GENDATA_VARIABLE,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_DOC,
    GENDATA_NAMESPACE,
    GENDATA_TYPE,
    GENDATA_ATTR,
    GENDATA_LINKAGE,
    GENDATA_GENDATA_RESERVE, // reserved for run-time storing (address)
    GENDATA_META_LAST
};

// GENDATA_CHARP
int gendata_struct_const_charp[]=
{
    GENDATA_CONST_CHARP,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};

// GENDATA_BOOL
int gendata_struct_bool[]=
{
    GENDATA_BOOL,
    GENDATA_GENDATA_TYPE,
    GENDATA_NAME,
    GENDATA_SIZE,
    GENDATA_META_LAST
};


// ALL STRUCTS
int *gendata_structs[GENDATA_LAST]=
{
    gendata_struct_class,                 // 0
    gendata_struct_inheritance,
    gendata_struct_member,
    gendata_struct_member_vector_n_max,
    gendata_struct_member_object,         // 4
    gendata_struct_method,
    gendata_struct_parameter,
    gendata_struct_charp,
    gendata_struct_object_pointer,        // 8
    gendata_struct_function_pointer,
    gendata_struct_char,
    gendata_struct_subroutine,
    gendata_struct_int,                   // 12
    gendata_struct_unsigned_int,
    gendata_struct_float,
    gendata_struct_double,
    gendata_struct_long_long,             // 16
    gendata_struct_unsigned_long_long,
    gendata_struct_pointer,
    gendata_struct_reference_count,
    gendata_struct_void_pointer,          // 20
    gendata_struct_member_std_vector_impl,
    gendata_struct_reference,
    gendata_struct_short,
    gendata_struct_unsigned_short,        // 24
    gendata_struct_enum,
    gendata_struct_enum_value,
    gendata_struct_unsigned_char,
    gendata_struct_array_type,            // 28
    gendata_struct_subrange,
    gendata_struct_unspec_param,
    gendata_struct_variable,
    gendata_struct_const_charp,           // 32
    gendata_struct_bool,
};

static void gendata_dump_recur(int &i, FILE *out, int level, int *data, int n_data, char *doc)
{
    int metadata_init=i;
    int type=data[i];
    if(type<0 || type>=GENDATA_LAST) fprintf(stderr, "Badly generated data: %d %d\n", i, type);
    int j=0, val;
    fprintf(out, "\n");
    while((val=gendata_structs[type][++j])!=GENDATA_META_LAST)
    {
	if(val==GENDATA_GENDATA_GOTO_NEXT) continue;

	fprintf(out, "%5d %08x %5d", i, data[i], j);
	switch(val)
	{
	case GENDATA_GENDATA_TYPE:
	    fprintf(out, "%*sMetadata type: %s(%d)\n", level*5, "", gendata_type_strings[data[i]], data[i]);
	    break;
	case GENDATA_NAME:
	    fprintf(out, "%*sName:          %s(%d)\n", level*5, "", &doc[data[i]], data[i]);
	    break;
	case GENDATA_DOC:
	    fprintf(out, "%*sDoc:           %s(%d)\n", level*5, "", &doc[data[i]], data[i]);
	    break;
	case GENDATA_SIZE:
	    fprintf(out, "%*sSize:          %d\n", level*5, "", data[i]);
	    break;
	case GENDATA_TYPE:
	    fprintf(out, "%*sType:          %d(%d)\n", level*5, "", metadata_init+data[i], data[i]);
	    break;
	case GENDATA_LOCATION:
	    fprintf(out, "%*sLocation:      %d\n", level*5, "", data[i]);
	    break;
	case GENDATA_GENDATA_VAR:
	    fprintf(out, "%*sVarMember:     %d\n", level*5, "", data[i]);

	    val=data[i++];
	    for(int k=0; k<val; k++) gendata_dump_recur(i, out, level+1, data, n_data, doc);
	    continue;
	case GENDATA_LINKAGE:
	    fprintf(out, "%*sLinkage:       %s(%d)\n", level*5, "", &doc[data[i]], data[i]);
	    break;
	case GENDATA_VTABLE_LINKAGE:
	    fprintf(out, "%*sVTableLinkage: %s(%d)\n", level*5, "", &doc[data[i]], data[i]);
	    break;
	case GENDATA_IS_CTOR:
	    fprintf(out, "%*sIs Ctor:       %d\n", level*5, "", data[i]);
	    break;
	case GENDATA_VTABLE:
	    fprintf(out, "%*sVTable:        %d\n", level*5, "", data[i]);
	    break;
	case GENDATA_ARTIFICIAL:
	    fprintf(out, "%*sArtificial:    %d\n", level*5, "", data[i]);
	    break;
	case GENDATA_GENDATA_RESERVE:
	    fprintf(out, "%*sReserved:\n", level*5, "");
	    break;
	case GENDATA_NAMESPACE:
	    fprintf(out, "%*sNamespace:     %s(%d)\n", level*5, "", &doc[data[i]], data[i]);
	    break;
	case GENDATA_UPPER_BOUND:
	    fprintf(out, "%*sUpper bound:   %d\n", level*5, "", data[i]);
	    break;
	case GENDATA_CONST_VALUE:
	    fprintf(out, "%*sConst value:   %d\n", level*5, "", data[i]);
	    break;
	case GENDATA_ATTR:
	    fprintf(out, "%*sAttribute:     %s(%d)\n", level*5, "", &doc[data[i]], data[i]);
	    break;
	default:
	    fprintf(stderr, "Error in generated data field: %d\n", val);
	}
	i++;
	fflush(out);
    }
}

void gendata_dump(FILE *out, int *data, int n_data, char *doc)
{
    fprintf(out, "Gendata dump (size=%d):\n", n_data);

    int i=0;
    while(i<n_data) gendata_dump_recur(i, out, 1, data, n_data, doc);
}

int *gendata_traverse(int *position)
{
    int type=*position;
    if(type<0 || type>=GENDATA_LAST) {fprintf(stderr, "Badly generated data: %d\n", type); return NULL;}
    int j=0, val;
    while((val=gendata_structs[type][++j])!=GENDATA_META_LAST)
    {
	if(val==GENDATA_GENDATA_GOTO_NEXT) continue;
	if(val==GENDATA_GENDATA_VAR)
	{
	    val=*position++;
	    for(int k=0; k<val; k++) position=gendata_traverse(position);
	    continue;
	}
	else if(val<0 || val>GENDATA_META_LAST)
	{
	    fprintf(stderr, "Error in generated data field: %d\n", val);
	    return NULL;
	}
	position++;
    }
    return position;
}

int gendata_get_data(int *data, gendata_meta_type meta_type, int occurence)
{
    int i=0;
    int type=data[i];
    if(type<0 || type>=GENDATA_LAST) {fprintf(stderr, "Badly generated data: %d\n", type); return GENDATA_INVALID_VALUE;}
    int j=0, val;
    while((val=gendata_structs[type][++j])!=GENDATA_META_LAST)
    {
	if(val==GENDATA_GENDATA_GOTO_NEXT) continue;
	if(val==meta_type && !occurence--) return data[i];
	i++;
    }
    fprintf(stderr, "Cannot get field %d in structure %d(%s)\n", meta_type, type, gendata_type_strings[type]);
    return GENDATA_INVALID_VALUE;
}

int gendata_get_position(int *data, gendata_meta_type meta_type)
{
    int i=0;
    int type=data[i];
    if(type<0 || type>=GENDATA_LAST) {fprintf(stderr, "Badly generated data: %d\n", type); return GENDATA_INVALID_VALUE;}
    int j=0, val;
    while((val=gendata_structs[type][++j])!=GENDATA_META_LAST)
    {
	if(val==GENDATA_GENDATA_GOTO_NEXT) continue;
	if(val==meta_type) return i;
	i++;
    }
    fprintf(stderr, "Cannot get field %d in structure %d(%s)\n", meta_type, type, gendata_type_strings[type]);
    return GENDATA_INVALID_VALUE;
}

int gendata_type_size(gendata_type type)
{
    int *str=gendata_structs[type];
    for(int i=0; ; i++) if(str[i]==GENDATA_META_LAST) return i-1;
}

int gendata_has_metatype(int type, gendata_meta_type meta_type, int *position)
{
    int i=0;
    if(type<0 || type>=GENDATA_LAST) {fprintf(stderr, "Badly generated data: %d\n", type); return 0;}
    int j=0, val;
    while((val=gendata_structs[type][++j])!=GENDATA_META_LAST)
    {
	if(val==GENDATA_GENDATA_GOTO_NEXT) continue;
	if(val==meta_type)
	{
	    if(position) *position=i;
	    return 1;
	}
	i++;
    }
    return 0;
}

char *gendata_get_string(int *data, char *doc, gendata_meta_type meta_type)
{
    int inc;
    if(!gendata_has_metatype(*data, meta_type, &inc) || data[inc]<0) return NULL;
    return &doc[data[inc]];
}

int gendata_resolve_type(int *data, int n_indirections)
{
    int *pos_type=gendata_resolve_pos_type(data, n_indirections);
    if(pos_type) return *pos_type; else return -1;
}

int *gendata_resolve_pos_type(int *data, int n_indirections)
{
    while(n_indirections--)
    {
	int inc;
	if(!(inc=gendata_get_data(data, GENDATA_TYPE)) || inc==GENDATA_INVALID_VALUE)
	    return NULL; // no valid GENDATA_TYPE
	data+=inc;
    }
    return data;
}

int gendata_string_as_cpp(int *data, char *doc, char *buffer, int n_buffer, int color)
{
    int i_name, n_name, n_child;
    char *name;
    int *data_type;

    switch(*data)
    {
    case GENDATA_CLASS:
    case GENDATA_ENUM:
	if((i_name=gendata_get_data(data, GENDATA_NAME))<0) name=(char*)"<noname_class>"; else name=&doc[i_name];
	return snprintf(buffer, n_buffer, color?GREEN"%s "RESET:"%s ", name);

    case GENDATA_REFERENCE:
	if((data_type=gendata_resolve_pos_type(data)))
	    n_name=gendata_string_as_cpp(data_type, doc, buffer, n_buffer);
	else
	    n_name=0;
	return n_name+snprintf(buffer+n_name, n_buffer-n_name, color?GREEN"&"RESET:"&");

    case GENDATA_POINTER:
    case GENDATA_OBJECT_POINTER:
	if((data_type=gendata_resolve_pos_type(data)))
	    n_name=gendata_string_as_cpp(data_type, doc, buffer, n_buffer);
	else
	    n_name=0;
	return n_name+snprintf(buffer+n_name, n_buffer-n_name, color?GREEN"*"RESET:"&");

    case GENDATA_METHOD:
	// return type
	if((data_type=gendata_resolve_pos_type(data)))
	    n_name=gendata_string_as_cpp(data_type, doc, buffer, n_buffer);
	else
	    n_name=snprintf(buffer, n_buffer, color?GREEN"void "RESET:"void ");

	// function name
	if((i_name=gendata_get_data(data, GENDATA_NAME))<0) name=(char*)"<noname_function>"; else name=&doc[i_name];
	n_name+=snprintf(buffer+n_name, n_buffer-n_name, color?CYAN"%s"RESET"(":"%s(", name);

	// parameters
	data+=gendata_get_position(data, GENDATA_GENDATA_VAR);
	n_child=*data;
	data++;
	for(int i=0; i<n_child; i++)
	{
	    if(i) n_name+=snprintf(buffer+n_name, n_buffer-n_name, ", ");
	    n_name+=gendata_string_as_cpp(data, doc, buffer+n_name, n_buffer-n_name);
	    data=gendata_traverse(data);
	}
	return n_name+snprintf(buffer+n_name, n_buffer-n_name, ")");

    case GENDATA_PARAMETER:
    case GENDATA_MEMBER:
    case GENDATA_MEMBER_VECTOR_N_MAX:
    case GENDATA_MEMBER_OBJECT:
    case GENDATA_MEMBER_STD_VECTOR_IMPL:
	// type
	if((data_type=gendata_resolve_pos_type(data)))
	    n_name=gendata_string_as_cpp(data_type, doc, buffer, n_buffer);
	else
	    n_name=snprintf(buffer, n_buffer, color?GREEN"void "RESET:"void ");

	// param name
	if((i_name=gendata_get_data(data, GENDATA_NAME))<0) name=(char*)"name"; else name=&doc[i_name];
	return n_name+snprintf(buffer+n_name, n_buffer-n_name, color?YELLOW"%s"RESET:"%s", name);

    case GENDATA_ARRAY_TYPE:
	// type
	if((data_type=gendata_resolve_pos_type(data)))
	    n_name=gendata_string_as_cpp(data_type, doc, buffer, n_buffer);
	else
	    n_name=0;

	// [#]
	{
	    data+=gendata_get_position(data, GENDATA_GENDATA_VAR)+1;
	    int upper_bound=gendata_get_data(data, GENDATA_UPPER_BOUND);
	    return n_name+snprintf(buffer+n_name, n_buffer-n_name, color?GREEN"[%d] "RESET:"[%d] ", upper_bound);
	}

    case GENDATA_CHARP:
    case GENDATA_CHAR:
    case GENDATA_INT:
    case GENDATA_BOOL:
    case GENDATA_UNSIGNED_INT:
    case GENDATA_UNSIGNED_SHORT:
    case GENDATA_FLOAT:
    case GENDATA_DOUBLE:
    case GENDATA_LONG_LONG:
    case GENDATA_VOID_POINTER:
	return snprintf(buffer, n_buffer, color?GREEN"%s "RESET:"%s ", gendata_type_strings[*data]);

    case GENDATA_FUNCTION_POINTER:
    case GENDATA_SUBROUTINE:
    case GENDATA_INHERITANCE:
    case GENDATA_REFERENCE_COUNT:
    default:
	fprintf(stderr, "internal: converting metadata type to C++ string, get %d\n", *data);
	*buffer=0;
	return 0;
    }
}
